#include "globalevent.h"
#include "xcb/xcb.h"
#include "src/core/controller.h"
#include <iostream>
#include <QVector>
#include <QX11Info>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <kiran-cc-daemon/kiran-session-daemon/keybinding-i.h>
#include <QDBusConnection>

namespace
{
    Display *mDisplay;          // Connect to Server X11
    Window mWin;                // Grabing window - in this case, the entire system will be
    int keycode;               
    unsigned int modifier;     
 
    //all the possible combinations
    QVector<quint32> maskModifiers(){
        return QVector<quint32>() << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);
    }
}

GlobalEvent::GlobalEvent(QObject *parent) : QObject(parent) {
    //TODO: replace this setp by using x11utils.h
    mDisplay = QX11Info::display();         // Create a connection to the server
    mWin = DefaultRootWindow(mDisplay);     // and pull out of it captured by the window with a macro
}

bool GlobalEvent::nativeEventFilter(const QByteArray &eventType, void *message, long *result) {
    Q_UNUSED(eventType)
    Q_UNUSED(result)

    xcb_key_press_event_t *keyEvent = nullptr;

    if (eventType == "xcb_generic_event_t") {
        xcb_generic_event_t *event = static_cast<xcb_generic_event_t *>(message);

        if ((event->response_type & 127) == XCB_KEY_PRESS){
            keyEvent = static_cast<xcb_key_press_event_t *>(message);

            foreach (quint32 maskMods, maskModifiers()) {
                if((keyEvent->state == (modifier | maskMods ))
                        &&  keyEvent->detail == keycode){
                    Controller::getInstance()->requestCapture(
                        CaptureRequest(CaptureRequest::GRAPHICAL_MODE));
                    return true;
                }
            }
        }
    }
    return false;
}


void GlobalEvent::setShortcut() {
    unsetShortcut();

    // default shortcut is ctrl + alt + a
    keycode = XKeysymToKeycode(mDisplay, XK_Alt_L + XK_A);
    modifier = ControlMask;

    foreach (quint32 maskMods, maskModifiers()) {
        XGrabKey(mDisplay,         
                 keycode ,          
                 modifier | maskMods,   
                 mWin,             
                 True,              
                 GrabModeAsync,  
                 GrabModeAsync);    
    }
}

void GlobalEvent::unsetShortcut() {
    foreach (quint32 maskMods, maskModifiers()) {
        XUngrabKey(mDisplay,
                   keycode,
                   modifier | maskMods,
                   mWin);
    }
}